home *** CD-ROM | disk | FTP | other *** search
/ Workbench Design / WB Collection.iso / workbench werkzeuge / scherz programme / explode / explode.c < prev    next >
C/C++ Source or Header  |  1996-04-07  |  9KB  |  450 lines

  1. /*
  2.  * explode.c - makes all Amiga windows "explode" when opening
  3.  *
  4.  * Bruno Costa - 30 Aug 89 - 31 Dec 89
  5.  *
  6.  * NOTE:
  7.  *   This program is VERY sensitive to compiler environment.
  8.  *  Compile under Lattice 5.0 with options -b0 -r0 -v.
  9.  */
  10.  
  11. /* TODO:
  12.     - check for windows where 4*size(Window) > 5*size(Screen)
  13. */
  14.  
  15. #define DELAY   1
  16. #define FASTDIV 0
  17. #define DETACH  1
  18. #define VERBOSE 1
  19.  
  20. #include <exec/types.h>
  21. #include <intuition/intuition.h>
  22. #include <graphics/gfxmacros.h>
  23. #include <proto/exec.h>
  24. #include <proto/dos.h>
  25. #include <proto/layers.h>
  26. #include <proto/graphics.h>
  27. #include <proto/intuition.h>
  28. #include "intuition.lvo"
  29. #include "common.h"
  30.  
  31. #define MAX(a,b) (((a)>(b))?(a):(b))
  32. #define MIN(a,b) (((a)<(b))?(a):(b))
  33.  
  34. #if DETACH
  35. long _stack = 2000;
  36. char *_procname = "Window_Exploder";
  37. long _priority = 5;
  38. long _BackGroundIO = 1;
  39. extern BPTR _Backstdout;
  40. #else
  41. BPTR _Backstdout;
  42. #endif
  43.  
  44. /*
  45.  * Resident Amiga libraries
  46.  */
  47. struct Library *IntuitionBase;
  48. struct Library *GfxBase;
  49. struct Library *LayersBase;
  50.  
  51. /*
  52.  * CLI Messages
  53.  */
  54. #define BANNER   "\x1b[33mExplode 1.2b\x1b[31m - \xa9 1989 by Bruno Costa\n"
  55. #define USAGE    "usage: \x1b[1mexplode\x1b[0m [-0..2] [-f] [-d] [-s] [-q] [<filename>]\n"
  56. #define REMOVING "\x1b[1mExplode :\x1b[0m handler removed.\n"
  57.  
  58. /*
  59.  * pointer to old OpenWindow function
  60.  */
  61. void (* openWindow) (void);
  62.  
  63. /*
  64.  * external assembly routine interface
  65.  */
  66. extern void __far ExplodeWindow(void);
  67.  
  68. /*
  69.  * Patterns
  70.  */
  71. #define DASHED 0x5555
  72. #define FULL   0xffff
  73.  
  74. /*
  75.  * These are globals just for the sake of efficiency
  76.  *   (avoids stack parameter passing).
  77.  */
  78. static struct Screen scr;
  79. static struct RastPort *rp;
  80. static int x0, y0, x, y, w, h;
  81. static int xi, yi, xf, yf;
  82.  
  83. /*
  84.  * Extended message port - contains global data
  85.  */
  86. #define PORTNAME "Explode_port"
  87.  
  88. struct ExtMsgPort {
  89.   struct MsgPort theport;
  90.   unsigned long int tagcode;
  91.   char tag[TAGSIZE];        /* tag to mark start of data */
  92.   int timedelay, pattern, nsteps;
  93.   struct {
  94.     struct {
  95.       int x, y;
  96.     } topleft, botright;
  97.   } step[MAXSTEPS];
  98. };
  99.  
  100. static struct ExtMsgPort myport = {
  101.  {NULL},
  102.  TAG_CODE,
  103.  TAG_ID,
  104.  DEFDELAY, DEFPAT, 21,
  105.  {
  106.   {    0,    0,    0,    0 },    /* left, top, right, bottom */
  107.   {  135,  -22,  135,  -22 },
  108.   {  265,  -30,  265,  -30 },
  109.   {  389,  -25,  389,  -25 },
  110.   {  506,   -6,  506,   -6 },
  111.   {  615,   23,  615,   23 },
  112.   {  717,   62,  717,   62 },
  113.   {  811,  111,  811,  111 },
  114.   {  895,  168,  895,  168 },
  115.   {  971,  231,  971,  231 },
  116.   { 1036,  300, 1036,  300 },
  117.   { 1090,  373, 1090,  373 },
  118.   { 1134,  449, 1134,  449 },
  119.   { 1166,  527, 1166,  527 },
  120.   { 1186,  605, 1186,  605 },
  121.   { 1194,  683, 1194,  683 },
  122.   { 1188,  759, 1188,  759 },
  123.   { 1169,  833, 1169,  833 },
  124.   { 1135,  902, 1135,  902 },
  125.   { 1087,  966, 1087,  966 },
  126.   { 1024, 1024, 1024, 1024 }    /* 21th entry */
  127.  }
  128. };
  129. /*
  130.  *  The points above were generated using an HP-28S and a bezier curve
  131.  * plotting program. The curve was broken in 20 line segments and the
  132.  * control points were: (0, 0) ; (922, -205) ; (1587, 665) ; (1024, 1024)
  133.  */
  134.  
  135.  
  136. #define xclip(x) (MAX(0, MIN(x, scr.Width - 1)))
  137. #define yclip(y) (MAX(0, MIN(y, scr.Height - 1)))
  138.  
  139. /*
  140.  *  Draws a line performing a simple clipping that only works for
  141.  * horizontal or vertical lines (the ones I draw).
  142.  */
  143. void line (int x1, int y1, int x2, int y2)
  144. {
  145.  int x1c, y1c, x2c, y2c;
  146.  
  147.  x1c = xclip (x1);
  148.  y1c = yclip (y1);
  149.  x2c = xclip (x2);
  150.  y2c = yclip (y2);
  151.  
  152.  if ( ((x1c == x1) && (y1c == y1)) || ((x2c == x2) && (y2c == y2)) )
  153.  {
  154.    Move (rp, x1c, y1c);
  155.    Draw (rp, x2c, y2c);
  156.  }
  157. }
  158.  
  159. /*
  160.  * Draws the outline from (xi,yi)-(xf,yf)
  161.  */
  162. void DrawOutline (void)
  163. {
  164.  line (xi, yi, xf, yi);
  165.  line (xf, yi, xf, yf);
  166.  line (xf, yf, xi, yf);
  167.  line (xi, yf, xi, yi);
  168. }
  169.  
  170. /*
  171.  * Does the animation of the outline along the path
  172.  */
  173. void MoveOutline (void)
  174. {
  175.  register int i;
  176.  int dxi, dyi, dxf, dyf;
  177.  int nxi, nyi, nxf, nyf;
  178.  
  179.  dxi = x - x0;
  180.  dyi = y - y0;
  181.  dxf = (x + w - 1) - x0;
  182.  dyf = (y + h - 1) - y0;
  183.  
  184.  for (i = 0; i < myport.nsteps; i++)
  185.  {
  186. #if FASTDIV
  187.    /*
  188.     * "Divides" faster by shifting (does it work for negative numbers ?)
  189.     */
  190.    nxi = x0 + ((myport.step[i].topleft.x * dxi) >> 10);
  191.    nyi = y0 + ((myport.step[i].topleft.y * dyi) >> 10);
  192.    nxf = x0 + ((myport.step[i].botright.x * dxf) >> 10);
  193.    nyf = y0 + ((myport.step[i].botright.y * dyf) >> 10);
  194. #else
  195.    nxi = x0 + ((myport.step[i].topleft.x * dxi) / 1024);
  196.    nyi = y0 + ((myport.step[i].topleft.y * dyi) / 1024);
  197.    nxf = x0 + ((myport.step[i].botright.x * dxf) / 1024);
  198.    nyf = y0 + ((myport.step[i].botright.y * dyf) / 1024);
  199. #endif
  200.  
  201.    if (i)
  202.      DrawOutline ();    /* erases outline */
  203.  
  204.    xi = nxi;
  205.    yi = nyi;
  206.    xf = nxf;
  207.    yf = nyf;
  208.  
  209.    DrawOutline ();    /* draws outline */
  210.  
  211. #if DELAY
  212.    Delay (myport.timedelay);        /* quick pause */
  213. #endif
  214.  }
  215.  DrawOutline ();
  216. }
  217.  
  218. /*
  219.  * C routine that does the real explosion
  220.  */
  221. void __far DoExplode(struct NewWindow *nw)
  222. {
  223.  if (GetScreenData (&scr, sizeof(struct Screen), nw->Type, nw->Screen))
  224.  {
  225.    /*
  226.     *  I am working on a copy of the RastPort, so I won't care to restore
  227.     * old values like drawing modes and current position.
  228.     */
  229.  
  230.    rp = &scr.RastPort;
  231.    SetDrMd (rp, COMPLEMENT | JAM1);
  232.    SetDrPt (rp, myport.pattern);
  233.  
  234.    x0 = xclip (scr.MouseX);       /* assure that coordinates are */
  235.    y0 = yclip (scr.MouseY);       /* inside this screen. */
  236.  
  237.    x = nw->LeftEdge;
  238.    y = nw->TopEdge;
  239.    w = nw->Width;
  240.    h = nw->Height;
  241.  
  242.    LockLayers (&scr.LayerInfo);
  243.  
  244.    MoveOutline ();    /* Now move window along the path */
  245.  
  246.    UnlockLayers (&scr.LayerInfo);
  247.  }
  248. }
  249.  
  250. #if VERBOSE
  251. /*
  252.  * window text shadows
  253.  */
  254.  
  255. static struct IntuiText TextS3 = {
  256.  2,0,JAM1,
  257.  26,30,
  258.  NULL,
  259.  "(September, 26th 1989)",
  260.  NULL
  261. };
  262.  
  263. static struct IntuiText TextS2 = {
  264.  2,0,JAM1,
  265.  25,19,
  266.  NULL,
  267.  "written by Bruno Costa",
  268.  &TextS3
  269. };
  270.  
  271. static struct IntuiText TextS1 = {
  272.  2,0,JAM1,
  273.  71,6,
  274.  NULL,
  275.  "Explode 1.2",
  276.  &TextS2
  277. };
  278.  
  279. #define windshadow TextS1
  280.  
  281. static struct IntuiText IText3 = {
  282.  1,0,JAM1,
  283.  26,30,
  284.  NULL,
  285.  "(September, 26th 1989)",
  286.  NULL
  287. };
  288.  
  289. static struct IntuiText IText2 = {
  290.  1,0,JAM1,
  291.  25,19,
  292.  NULL,
  293.  "written by Bruno Costa",
  294.  &IText3
  295. };
  296.  
  297. static struct IntuiText IText1 = {
  298.  3,0,JAM1,
  299.  71,6,
  300.  NULL,
  301.  "Explode 1.2",
  302.  &IText2
  303. };
  304.  
  305. #define windtext IText1
  306.  
  307. static struct NewWindow wind = {
  308.  207, 71, 227, 47, 0, 1, NULL,
  309.  SIMPLE_REFRESH + RMBTRAP + NOCAREREFRESH,
  310.  NULL, NULL, NULL, NULL, NULL,
  311.  0, 0, 0, 0, WBENCHSCREEN
  312. };
  313. #endif
  314.  
  315. void usage (void)    /* dead end */
  316. {
  317.  Write (_Backstdout, USAGE, sizeof(USAGE));
  318. #if DETACH
  319.  Close (_Backstdout);
  320. #endif
  321.  exit (5);
  322. }
  323.  
  324. main(int argc, char *argv[])
  325. {
  326.  int i, removed, verbose = TRUE, stay = FALSE;
  327.  struct Window *w;
  328.  struct ExtMsgPort *port;
  329.  
  330. #if !DETACH
  331.  _Backstdout = Output();
  332. #endif
  333.  
  334.  port = (struct ExtMsgPort *) FindPort (PORTNAME);
  335.  if (!port)
  336.  {
  337.    port = &myport;
  338.    stay = TRUE;
  339.  }
  340.  
  341.  if (_Backstdout && argc)
  342.  {
  343.    if (stay)
  344.      Write (_Backstdout, BANNER, sizeof(BANNER));
  345.    for (i = 1; i < argc; i++)
  346.    {
  347.      if (argv[i][0] == '-')
  348.      {                /* argument is an option */
  349.        if (argv[i][1] >= '0' && argv[i][1] <= '2')
  350.          port->timedelay = argv[i][1] - '0';
  351.        else if (argv[i][1] == 'f')
  352.          port->pattern = FULL;
  353.        else if (argv[i][1] == 'd')
  354.          port->pattern = DASHED;
  355.        else if (argv[i][1] == 's')
  356.          verbose = FALSE;
  357.        else if (argv[i][1] == 'q')
  358.        {
  359.          if (stay)
  360.            stay = FALSE;
  361.          else
  362.          {
  363.            Signal (port->theport.mp_SigTask, 1L << port->theport.mp_SigBit);
  364.            port = &myport;
  365.          }
  366.          Write (_Backstdout, REMOVING, sizeof(REMOVING));
  367.        }
  368.        else
  369.          usage();
  370.      }
  371.      else
  372.      {                /* argument is a filename */
  373.        usage();
  374.      }
  375.    }
  376. #if DETACH
  377.    Close (_Backstdout);
  378. #endif
  379.  }
  380.  
  381.  if (stay)
  382.  {
  383.    /* create port */
  384.    myport.theport.mp_Node.ln_Name = PORTNAME;
  385.    myport.theport.mp_Node.ln_Pri = 0;
  386.    myport.theport.mp_Node.ln_Type = NT_MSGPORT;
  387.    myport.theport.mp_Flags = PA_SIGNAL;
  388.    myport.theport.mp_SigBit = AllocSignal (-1);
  389.    myport.theport.mp_SigTask = FindTask (NULL);
  390.    AddPort (&myport.theport);
  391.    port = &myport;
  392.  }
  393.  else
  394.    goto final;
  395.  
  396.  GfxBase = OpenLibrary ("graphics.library", 0);
  397.  LayersBase = OpenLibrary ("layers.library", 0);
  398.  IntuitionBase = OpenLibrary ("intuition.library", 0);
  399.  
  400.  openWindow = SetFunction (IntuitionBase, _LVOOpenWindow, ExplodeWindow);
  401.  
  402. #if VERBOSE
  403.  if (verbose)
  404.  {
  405.    w = OpenWindow (&wind);    /* notify that handler is installed */
  406.    if (w)
  407.    {
  408.      PrintIText (w->RPort, &windshadow, 2, 1);
  409.      PrintIText (w->RPort, &windtext, 0, 0);
  410.      Delay (200);
  411.      CloseWindow (w);
  412.    }
  413.  }
  414. #endif
  415.  
  416.  do
  417.  {
  418.    Wait (1L << port->theport.mp_SigBit);    /* wait for termination signal */
  419.  
  420.    Forbid ();
  421.  
  422.    if (SetFunction (IntuitionBase, _LVOOpenWindow, openWindow) != ExplodeWindow)
  423.    {
  424.      /*
  425.       *   Someone has interposed a handler after me. My handler can't be
  426.       *  removed: otherwise the system will crash after the other handler
  427.       *  removes itself.
  428.       */
  429.      (void) SetFunction (IntuitionBase, _LVOOpenWindow, ExplodeWindow);
  430.      removed = FALSE;
  431.    }
  432.    else
  433.      removed = TRUE;
  434.  
  435.    Permit();
  436.  
  437.  } while (!removed);
  438.  
  439.  CloseLibrary (IntuitionBase);
  440.  CloseLibrary (LayersBase);
  441.  CloseLibrary (GfxBase);
  442.  
  443.  /* Delete port */
  444.  RemPort (&port->theport);
  445.  FreeSignal (port->theport.mp_SigBit);
  446.  
  447. final:
  448.  exit (0);
  449. }
  450.